﻿using System.IO;
using System;

using InputFileGenerator;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace InputFileGeneratorTest
{
    
    
    /// <summary>
    ///This is a test class for ProgramTest and is intended
    ///to contain all ProgramTest Unit Tests
    ///</summary>
    [TestClass()]
    public class BranchAndBoundCreationTest
    {
        private void AddNextChar(ref int value, char source)
        {
            value = value * 10 + ((int)source - (int)'0');  // digit transformation
        }

        private TestContext testContextInstance;

        /// <summary>
        ///Gets or sets the test context which provides
        ///information about and functionality for the current test run.
        ///</summary>
        public TestContext TestContext
        {
            get
            {
                return testContextInstance;
            }
            set
            {
                testContextInstance = value;
            }
        }

        #region Additional test attributes
        // 
        //You can use the following additional attributes as you write your tests:
        //
        //Use ClassInitialize to run code before running the first test in the class
        //[ClassInitialize()]
        //public static void MyClassInitialize(TestContext testContext)
        //{
        //}
        //
        //Use ClassCleanup to run code after all tests in a class have run
        //[ClassCleanup()]
        //public static void MyClassCleanup()
        //{
        //}
        //
        //Use TestInitialize to run code before running each test
        //[TestInitialize()]
        //public void MyTestInitialize()
        //{
        //}
        //
        //Use TestCleanup to run code after each test has run
        //[TestCleanup()]
        //public void MyTestCleanup()
        //{
        //}
        //
        #endregion

        private const int acceptableError = 100;
        //                              {0}        {1}              {2}                                    {3}                                              {4}      {5}      {6}    {7}                                             {7}             
        private string[] smallArgs = { "-name", "branchandbound", "-file", "C:\\Program Files\\CVSNT\\DWARFS2\\Bin\\InputFileGenerator\\smallContent.txt", "-size", "1024", "-dim", "400" };
        private string[] mediumArgs = { "-name", "branchandbound", "-file", "C:\\Program Files\\CVSNT\\DWARFS2\\Bin\\InputFileGenerator\\mediumContent.txt", "-size", "1024", "-dim", "750" };
        private string[] largeArgs = { "-name", "branchandbound", "-file", "C:\\Program Files\\CVSNT\\DWARFS2\\Bin\\InputFileGenerator\\largeContent.txt", "-size", "1024", "-dim", "900" };

        private bool IsFileCareful(string[] args)
        {
            if (!File.Exists(args[3]))
            {
                return false;
            }
            else
            {
                return IsMatrixCareful(args);
            }
        }

        private bool IsMatrixCareful(string[] args)
        {
            FileStream stream = null;
            StreamReader reader = null;
            //fix: have a single return site
            bool returnval = true;
            try
            {
                stream = new FileStream(args[3], FileMode.Open, FileAccess.Read, FileShare.Read);
                reader = new StreamReader(stream);
                string stringCount = reader.ReadLine();
                int cityCount = 0;
                int expectedDim = int.Parse(args[7]);
                for (int i = 0; i < stringCount.Length; i++)
                {
                    AddNextChar(ref cityCount, stringCount[i]); 
                }
                if (cityCount != expectedDim)
                {
                    //return false;                                   // incorrect matrix dimension
                    returnval = false;
                }
                else
                {
                    cityCount++;

                    int[,] distances = new int[cityCount, cityCount];   // try to create matrix with defined dimension
                    // for algorithm comments look the BranchAndBound dwarf
                    for (int i = 0; i < cityCount; i++)
                    {
                        distances[0, i] = distances[i, 0] = i;
                    }

                    for (int i = 1; i < cityCount; i++)
                    {
                        int position = 1;
                        stringCount = reader.ReadLine();
                        for (int j = 0; j < stringCount.Length; j++)
                        {
                            char currentChar = stringCount[j];
                            if (currentChar == ' ')
                            {
                                position++;
                            }
                            else
                            {
                                if (currentChar == '-')
                                {
                                    distances[i, position] = 0;
                                }
                                else
                                {
                                    AddNextChar(ref distances[i, position], currentChar);
                                }
                            }
                        }
                    }
                    for (int i = 1; i < cityCount; i++)
                    {
                        distances[i, i] = 0;
                    }
                }
                //fix: one return site
                //return true;                        // generation was successful
            }
            catch (Exception e)
            {
                //fix: have a single return site
                //return false;                       // if problems with matrix creation, then inputfile is incorrect
                returnval = false;
                //fix: at least print an error
                Console.Out.WriteLine(e.Message);
            }
            finally
            {
                reader.Close();
            }
            //fix: have a single return site
            return returnval;
        }

        /// <summary>
        ///A test for Main
        ///</summary>
        [TestMethod()]
        [DeploymentItem("InputFileGenerator.exe")]
        public void MainTest()
        {
            //string[] args = mediumArgs;
            string[] args = smallArgs;
            //string[] args = largeArgs;

            Boolean exist = File.Exists(args[3]);
            Program_Accessor.Main(args);
            Assert.IsTrue(exist || IsFileCareful(args));
        }
    }
}
